package tkaczyk.simtalk.pc;

import java.awt.Insets;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;

import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;

import org.apache.log4j.Logger;
import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml3;

import tkaczyk.simtalk.message.Message;
import tkaczyk.simtalk.messenger.MessageDisplay;

@SuppressWarnings("serial")
public class MessagesPane extends JTextPane implements MessageDisplay {
	private final static Logger log = Logger.getRootLogger();
	private final static SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	private final static String cssStylesPath = "conf/chatpane.css";
	private boolean chatStarted = false;
	private boolean escapingHtml = true;
	private Element body;

	public MessagesPane() {
		super();
	}

	public void addNotify() {
		super.addNotify();

		setEditable(false);
		setMargin(new Insets(0, 0, 0, 0));
		setContentType("text/html");
		// String test = "<div class=\"incoming\">" +
		// "<b>John Doe</b> 23:04:01 <br/>" + "Example message" + "</div>\n"
		// + "<div id=\"1\" class=\"outgoing\">" +
		// "<b>Don Johnson</b> 23:04:05 <br/>" + "Example response</div>\n";
		// String test2 = "<div class=\"incoming\">" +
		// "<b>Aaaaaa</b> 23:04:01 <br/>" + "Example message" + "</div>\n"
		// + "<div class=\"outgoing\">" + "<b>Bbbbbbb</b> 23:04:05 <br/>" +
		// "Example response</div>\n";
		HTMLDocument doc = (HTMLDocument) getDocument();
		StyleSheet ss = doc.getStyleSheet();
		ss.addRule(loadCSS());
		setText("<html><body id=\"chatContent\"></body></html>");
		body = doc.getElement("chatContent");
	}

	private String loadCSS() {
		try {
			File css = new File(cssStylesPath);
			FileInputStream in = new FileInputStream(css);
			InputStreamReader reader = new InputStreamReader(in);
			char[] buffer = new char[(int) css.length()];
			reader.read(buffer);
			return new String(buffer);
		} catch (IOException e) {
			log.error("Could not read style sheet: " + cssStylesPath + "\n", e);
			return "";
		}
	}

	@Override
	public void update(Message msg) {
		displayMessage(msg);
	}

	private void displayMessage(Message msg) {
		try {
			HTMLDocument doc = (HTMLDocument) getDocument();
			if (!chatStarted) {
				doc.setInnerHTML(body, formatMessage(msg));
				chatStarted = true;
			} else {
				doc.insertBeforeEnd(body, formatMessage(msg));
			}
			if (log.isTraceEnabled()) {
				StringWriter writer = new StringWriter();
				HTMLEditorKit kit = (HTMLEditorKit) getEditorKit();
				kit.write(writer, getDocument(), 0, getDocument().getLength());
				log.trace("\n" + writer.toString());
			}
		} catch (BadLocationException | IOException e) {
			log.error(e);
		}
	}

	private String formatMessage(Message msg) {
		StringBuilder msgString = new StringBuilder();
		msgString.append("<div class=\"");
		switch (msg.getTarget()) {
		case INCOMING:
			msgString.append("incoming");
			break;
		case OUTGOING:
			msgString.append("outgoing");
			break;
		default:
			break;
		}
		msgString.append("\">");
		msgString.append("<b>" + escapeHtml3(msg.getNick()) + "</b>");
		msgString.append(dateFormat.format(msg.getSent()));
		msgString.append("<br/>");
		if (escapingHtml) {
			msgString.append(escapeHtml3(msg.toString()));
		} else {
			msgString.append(msg.toString());
		}
		msgString.append("</div>");
		return msgString.toString();
	}
}
